Lesson: Lens Flares with Extensions

I hope you guys with both the GL_HP_occlusion_test and GL_NV_occlusion_query extensions didn't think I would leave you hanging :). This is the supplemental part of the lens flare tutorial. I will only be going over the specifics of using the extensions here. Lets get started by making a replacement for that beast of a function to do frustum culling. I will use the GL_HP_occlusion_test extension because its a quick way to do just one test, however if your project calls for multiple occlusion tests then it would be best to use the GL_NV_occlusion_query instead. You gotta love nVidia, they seemed to have picked up where HP left off in regards to the two extensions. They both do the same thing but the nVidia extension allows you to generate multiple occlusion tests much like you generate textures in OpenGL. The idea is that you have a single test for every object in your scene. The nVidia extension will also tell you how many pixels are visible. The HP extension will not. I think you guys can see where this would come in handy especially if you happen to be creating an engine of some kind. See the references at the end of this tutorial for more information. Lets check out the code.

GLboolean glCamera::OcclusionQuery()
{
	GLboolean result;
//- disable updates to color and depth buffer (optional) glDepthMask(GL_FALSE); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
//- enable occlusion test glEnable(GL_OCCLUSION_TEST_HP);
//- render bounding geometry glBegin(GL_POINTS); glVertex3f(m_LightSourcePos.x, m_LightSourcePos.y, m_LightSourcePos.z); glEnd();
//- disable occlusion test glDisable(GL_OCCLUSION_TEST_HP);
//- enable updates to color and depth buffer glDepthMask(GL_TRUE); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
//- read occlusion test result glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP, &result);
return(result); }

The above function is going to take the place of our UpdateFrustum function. I'm sure you can see that it is much nicer to look at and doesn't strain the eyes so much. Its also a bit faster which is an added bonus. We have to first disable updates to the color and depth buffers then its just a matter of rendering whatever it is we want to test. In this case its a single point but you could render bounding boxes also. We re-enable updates to the color and depth buffers and get the boolean result of the occlusion test by calling glGetBooleanv(). Thats all there is to it. Lets take a look at the point sprite code next.

void glCamera::RenderHalo(GLfloat r, GLfloat g, GLfloat b, GLfloat a, glPoint p, GLfloat scale)
{
	GLfloat maxSize=1.0f;
	glGetFloatv( GL_POINT_SIZE_MAX_EXT, &maxSize );
	glPointSize( maxSize );
	glBindTexture(GL_TEXTURE_2D, m_HaloTexture);	// Bind to the Big Glow texture
	glTexEnvf(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV, GL_TRUE );
	glEnable(GL_POINT_SPRITE_NV);
	glColor4f(r, g, b, a);	
	glBegin(GL_POINTS);
		glVertex3f(p.x, p.y, p.z);
	glEnd();
	glDisable(GL_POINT_SPRITE_NV);
}
This is probably the simplest way to draw a texture mapped quad that I know of. What we are doing here is setting our point spirte to the maximum allowed size for the lens flares. We bind to the texture we are going to use and we set the texture environment to take advantage of point sprites. Then we simply enable the extension and render the point where we want the Halo. I must point out that if you were to change all the drawing code to use point sprites then the lightsource will look too small to be a star of some kind. The reason for this is point sprites were never intended to draw big sprites to the screen. Our Big Glow texture, as its name implies, should be large. So we are stuck with the some of the old code from the previous tutorial. Really there is no need for point sprites here but I just wanted to include them anyway because they are quite handy to know how to use. Anytime you need to make a lot of particles this extension is the one to use. Next is the code that checks for the extensions needed.
BOOL GetExtensions(void)
{
	char *ext = (char*)glGetString( GL_EXTENSIONS );
if(strstr(ext, "GL_HP_occlusion_test") != NULL && strstr(ext, "GL_NV_point_sprite") != NULL) { return(TRUE); }
return(FALSE); }
This function just gets the extensions that are installed and tests to see if the extensions we are using in the tutorial are installed. We use strstr() to do the testing. Basicaly it just searches for sub strings inside of another string. If the extensions we need are installed then we get the address of the glPointParameterfEXT because we need to use that in order to set our point sprites to the maximum allowed size. Next up is the DrawGLScene()
int DrawGLScene(GLvoid)									// Here's Where We Do All The Drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
	glLoadIdentity();									// Reset The Current Modelview Matrix
gCamera.SetPrespective(); gCamera.m_LightSourcePos.z = gCamera.m_Position.z - 50.0f; if(gCamera.OcclusionQuery() == GL_TRUE) { gCamera.RenderLensFlare(); } //gCamera.UpdateFrustumFaster();
if(infoOn == TRUE) { DrawGLInfo(); }
CheckKeys();
return TRUE; // Everything Went OK }

The function is almost identical to the last tutorial except we no long have to call the UpdateFrustum function because of the HP extension. We test to see if the light source position passes our occlusion test and if it does then we render the lens flare. Otherwise we don't draw anything.

Thats all I have to say about lens flares for a very long time. On to bigger and better things. See you next tutorial.

Thanks go out to Dave Steere, Cameron Tidwell, Bert Sammons, and Brannon Martindale for their feed back and helping me test out the code on different hardware.

Other Resources:
http://www.gamedev.net/reference/articles/article874.asp
http://www.gamedev.net/reference/articles/article813.asp
http://www.opengl.org/developers/code/mjktips/lensflare/
http://www.markmorley.com/opengl/frustumculling.html
http://oss.sgi.com/projects/ogl-sample/registry/HP/occlusion_test.txt
http://oss.sgi.com/projects/ogl-sample/registry/NV/occlusion_query.txt

- Cheers

Vic

* DOWNLOAD Visual C++ Code For This Lesson.


< Lesson ?? Lesson ?? >